{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Создание агента с функциями на базе GigaChat\n",
    "\n",
    "С помощью [нейросетевой модели GigaChat](https://developers.sber.ru/docs/ru/gigachat/overview) вы можете вызывать различные функции — инструменты, которые будет использовать модель для решения поставленной задачи.\n",
    "Модель самостоятельно решает, когда и какой инструмент нужно использовать. \n",
    "Вызванные функции выполняются на стороне клиента.\n",
    "Вы можете использовать функции как разработанные самостоятельно, так и доступные в GigaChain и сторонних библиотеках.\n",
    "\n",
    "Для использования функций нужно создать агента с помощью модуля [`gigachat_functions_agent`](/libs/langchain/langchain/agents/gigachat_functions_agent/base.py).\n",
    "\n",
    "Раздел содержит пример агента, который задает вопрос в поисковом сервисе DuckDuckGo и рисует ответ с помощью Ascii-графики. Итоговый агент не только умеет работать с разными инструментами, но и обладает памятью.\n",
    "\n",
    "## Агент с одной функцией\n",
    "\n",
    "Для создания агента с функцией обращения к поисковому сервису DuckDuckGo:\n",
    "\n",
    "1. Инициализируйте GigaChat.\n",
    "2. Добавьте функцию поиска в массив инструментов доступных модели.\n",
    "3. Передайте агенту модель и массив инструментов.\n",
    "\n",
    "### Инициализация GigaChat\n",
    "\n",
    "Для работы агента создайте экземпляр класса GigaChat.\n",
    "В классе укажите модель, поддерживающую работу с функциями:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.chat_models.gigachat import GigaChat\n",
    "\n",
    "giga = GigaChat(\n",
    "    credentials=\"авторизационные_данные\", model=\"модель_с_поддержкой_функций\"\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Для авторизации запросов к GigaChat используйте данные, полученные при [создании проекта GigaChat API](https://developers.sber.ru/docs/ru/gigachat/api/integration).\n",
    "\n",
    "Список и описание доступных моделей — в разделе [Модели GigaChat](https://developers.sber.ru/docs/ru/gigachat/models).\n",
    "\n",
    "### Добавление функции поиска\n",
    "\n",
    "Добавьте адаптер поискового сервиса [DuckDuckGo](https://www.duckduckgo.com) в список инструментов, которые будет использовать модель.\n",
    "\n",
    "Для этого импортируйте класс `DuckDuckGoSearchRun` и добавьте функцию `DuckDuckGoSearchRun()` в массив `tools`:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_community.tools import DuckDuckGoSearchRun\n",
    "\n",
    "search_tool = DuckDuckGoSearchRun()\n",
    "tools = [search_tool]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Создание и запуск агента\n",
    "\n",
    "Инициализируйте агента. Передайте ему модель, которая будет вызывать функции, и массив доступных ей инструментов `tools`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.agents import AgentExecutor, create_gigachat_functions_agent\n",
    "\n",
    "agent = create_gigachat_functions_agent(giga, tools)\n",
    "\n",
    "# AgentExecutor создает среду, в которой будет работать агент\n",
    "agent_executor = AgentExecutor(\n",
    "    agent=agent,\n",
    "    tools=tools,\n",
    "    verbose=True,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Запустите агента с помощью функции `invoke()`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m\n",
      "Invoking: `duckduckgo_search` with `{'query': 'курс биткоина'}`\n",
      "\n",
      "\n",
      "\u001b[0m\u001b[36;1m\u001b[1;3mКурс Биткоина (BTC): цена Bitcoin, индекс, новости — Investing.com Новинка! 💥 Приобретите ProPicks и узнайте стратегию, опередившую S&P 500 более чем на 1,183% Получить скидку 40% Биткоин... 48 306,99 $ 1.2% 1,0000 BTC 0.0% 47 623,87 $ Диапазон за 24 ч 48 487,28 $ Добавить в портфель • 1 453 248 added Конвертируйте Биткоин в US Dollar (BTC в USD) Сегодня цена конвертации 1 Биткоин (BTC) в USD равна $48 324,27. BTC USD 1 BTC = 48 306,99 $ Как купить BTC за USD Показать График BTC в USD Сегодня Биткоин (BTC) стоит $48 324,27. Price of BTC today The live price of Bitcoin is $ 45,464.14 per (BTC / USD) with a current market cap of $ 892.11B USD. 24-hour trading volume is $ 26.67B USD. BTC to USD price is updated in real-time. Bitcoin is +2.55% in the last 24 hours with a circulating supply of 19.62M. BTC Price History USD BTC Price Information 24h Low & High Курс криптовалют онлайн - Курс криптовалют к доллару на сегодня - Минфин Еще Курс криптовалют к доллару Курс Bitcoin, Ethereum, Litecoin и других криптовалют Обновлено 08.02.2024, 20:59 Все Название Цена Капитализация за час Bitcoin 1 BTC 45.289,00 $ 886.893.940.707,00 $ +0,61 % Ethereum 2 ETH 2.431,94 $ 292.024.231.852,00 $ +0,36 % HEX 3 HEX Биткоин резко подорожал / фото УНИАН. В среду курс биткоина, наиболее популярной криптовалюты в мире, перешел рубеж в 51 тыс долл. Такие данные приводит криптобиржа Coindesk.. Последний раз биткоин торговался на этом ...\u001b[0m\u001b[32;1m\u001b[1;3m48 324,27\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'48 324,27'"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "agent_executor.invoke(\n",
    "    {\"input\": \"Найди текущий курс биткоина и напечатай только число\"}\n",
    ")[\"output\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Агент с несколькими функциями\n",
    "\n",
    "Для создания агента, который кроме поиска будет возвращать текст в виде Ascii-графики, вам потребуется библиотека pyfiglet.\n",
    "Вы можете установить ее с помощью команды:\n",
    "\n",
    "```sh\n",
    "pip install pyfiglet\n",
    "```\n",
    "\n",
    "Библиотека умеет работать только с латинскими символами и цифрами.\n",
    "\n",
    "Пример работы pyfiglet:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "          _______  _        _        _______  _ \n",
      "|\\     /|(  ____ \\( \\      ( \\      (  ___  )( )\n",
      "| )   ( || (    \\/| (      | (      | (   ) || |\n",
      "| (___) || (__    | |      | |      | |   | || |\n",
      "|  ___  ||  __)   | |      | |      | |   | || |\n",
      "| (   ) || (      | |      | |      | |   | |(_)\n",
      "| )   ( || (____/\\| (____/\\| (____/\\| (___) | _ \n",
      "|/     \\|(_______/(_______/(_______/(_______)(_)\n",
      "                                                \n",
      "\n"
     ]
    }
   ],
   "source": [
    "import pyfiglet\n",
    "\n",
    "pyfiglet.print_figlet(\"Hello!\", font=\"epic\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Использование нескольких функций\n",
    "\n",
    "Чтобы упростить создание функций из python-кода, используйте декоратор `@tool`.\n",
    "Он преобразует любую функцию в инструмент, доступный модели для вызова.\n",
    "\n",
    ":::note\n",
    "\n",
    "Модель ориентируется как на название и описание функции, так и на описание и типы аргументов возвращаемого значения.\n",
    "Чтобы модель правильно понимала, как нужно использовать инструмент, все значения функции нужно явно указать.\n",
    "\n",
    ":::\n",
    "\n",
    "Создайте функцию `draw_banner()`, которая будет возвращать результат поиска в виде Ascii-графики, и добавьте ее в новый массив инструментов `new_tools`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.tools import tool\n",
    "\n",
    "\n",
    "@tool\n",
    "def draw_banner(number: str) -> str:\n",
    "    \"\"\"Рисует баннер с текстом результатов кода в виде Ascii-графики\n",
    "\n",
    "    Args:\n",
    "        number (str): Число, которое нужно нарисовать на баннере\n",
    "    \"\"\"\n",
    "    pyfiglet.print_figlet(number, font=\"epic\")\n",
    "    return \"Draw complete\"\n",
    "\n",
    "\n",
    "new_tools = [search_tool, draw_banner]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Инициализируйте и запустите агента с просьбой найти нужное значение и нарисовать его на баннере:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m\n",
      "Invoking: `duckduckgo_search` with `{'query': 'курс биткоина в долларах'}`\n",
      "\n",
      "\n",
      "\u001b[0m\u001b[36;1m\u001b[1;3mСегодня цена конвертации 1 Биткоин (BTC) в USD равна $48 324,27. BTC USD 1 BTC = 48 306,99 $ Как купить BTC за USD Показать График BTC в USD Сегодня Биткоин (BTC) стоит $48 324,27. Это на 0.5% увеличилась, чем час назад, и на 1.2% увеличилась, чем вчера. Стоимость BTC сегодня на 13.5% больше, чем 7 дней назад. 1 BTC = 47 384,89 USD по курсу на 10.02.2024. Стоимость 1 биткоина в долларах США на сегодня составляет 47 384,89 $ по данным ЦБ РФ, по сравнению со вчерашним днём курс валюты увеличился на 0,16% (на +73,73 $). Курс биткоина по отношению к доллару США на графике, таблица динамики стоимости в процентах за день, неделю, месяц и год. Конвертер валют Узнайте курс биткоина в долларах в разных банках и обменниках, а также динамику их изменений за месяц и год. Сравните курсы биткоина в долларах с другими валютами и посмотрите средние курсы в банках, Межбанке, НБУ, Visa и Mastercard. Обменный курс Bitcoin приведен по состоянию на 10 февраля 2024 г. от coinmarketcap.com. Обменный курс доллар Соединенных Штатов приведен по состоянию на 8 февраля 2024 г. от Международный Валютный Фонд. Переводной коэффициент BTC состоит из 15 знаков. Переводной коэффициент USD состоит из 6 знаков. BTC курс 10 февраля 2024 г. USD курс 1 BTC = 42,310.13 USD Курс: 42310.1333 +154.99 Курс закрытия: 42155.1393 Обратный курс: 1.00 USD = 0.000020 BTC 🕒 Курс валют обновлен: Sun, 28 Jan 2024 09:00:11 Доллар США: 🚀 валюта выросла на 0.37% (+154.99) по отношению к Биткоин в сравнении с предыдущим закрытым курсом. Попробуйте конвертировать в обратном порядке: Доллар США в Биткоин.\u001b[0m\u001b[32;1m\u001b[1;3m\n",
      "Invoking: `draw_banner` with `{'number': '48 324,27'}`\n",
      "responded: Ваш запрос принят. Идет обработка...\n",
      "\n",
      "\u001b[0m    ___    _____     ______   _______    ___     _______  ______  \n",
      "   /   )  / ___ \\   / ___  \\ / ___   )  /   )   / ___   )/ ___  \\ \n",
      "  / /) | ( (___) )  \\/   \\  \\\\/   )  | / /) |   \\/   )  |\\/   )  )\n",
      " / (_) (_ \\     /      ___) /    /   )/ (_) (_      /   )    /  / \n",
      "(____   _)/ ___ \\     (___ (   _/   /(____   _)   _/   /    /  /  \n",
      "     ) ( ( (   ) )        ) \\ /   _/      ) (    /   _/    /  /   \n",
      "     | | ( (___) )  /\\___/  /(   (__/\\    | | _ (   (__/\\ /  /    \n",
      "     (_)  \\_____/   \\______/ \\_______/    (_)( )\\_______/ \\_/     \n",
      "                                             |/                   \n",
      "\n",
      "\u001b[33;1m\u001b[1;3mDraw complete\u001b[0m\u001b[32;1m\u001b[1;3m- вот баннер с курсом биткоина в долларах.\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'- вот баннер с курсом биткоина в долларах.'"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "agent = create_gigachat_functions_agent(giga, new_tools)\n",
    "\n",
    "agent_executor = AgentExecutor(\n",
    "    agent=agent,\n",
    "    tools=new_tools,\n",
    "    verbose=True,\n",
    ")\n",
    "\n",
    "agent_executor.invoke(\n",
    "    {\n",
    "        \"input\": \"Найди в интернете курс биткоина в долларах и нарисуй это число на банере.\"\n",
    "    }\n",
    ")[\"output\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Добавление памяти\n",
    "\n",
    "В созданном агенте отсутствуют данные о состоянии, таким образом, он не помнит предыдущие взаимодействия с пользователем.\n",
    "\n",
    "Чтобы агент помнил, о чем пользователь разговаривал с ним, передайте историю сообщений в переменной `chat_history`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'chat_history': [HumanMessage(content='Привет! Запомни трех животных - слон, жираф, крокодил'),\n",
       "  AIMessage(content='Привет! Хорошо, я запомнил.')],\n",
       " 'input': 'Что я просил тебя запомнить?',\n",
       " 'output': 'Вы просили меня запомнить трех животных: слон, жираф и крокодил.'}"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain_core.messages import AIMessage, HumanMessage\n",
    "\n",
    "agent_executor = AgentExecutor(\n",
    "    agent=agent,\n",
    "    tools=new_tools,\n",
    "    verbose=False,\n",
    ")\n",
    "\n",
    "agent_executor.invoke(\n",
    "    {\n",
    "        \"chat_history\": [\n",
    "            HumanMessage(\n",
    "                content=\"Привет! Запомни трех животных - слон, жираф, крокодил\"\n",
    "            ),\n",
    "            AIMessage(content=\"Привет! Хорошо, я запомнил.\"),\n",
    "        ],\n",
    "        \"input\": \"Что я просил тебя запомнить?\",\n",
    "    }\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Использование памяти в чате с агентом\n",
    "\n",
    "Вы можете использовать память для сохранения истории и промежуточных результатов общения пользователя с агентом:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "User: Привет\n",
      "Bot: Здравствуйте! Могу ли я помочь Вам с чем-то?\n",
      "User: Найди возраст Илона Маска\n",
      "Bot: Илон Маск родился 28 июня 1971 года, поэтому на текущий момент (2022 год) ему 50 лет.\n",
      "User: Выведи его возраст на банер\n",
      " _______  _______ \n",
      "(  ____ \\(  __   )\n",
      "| (    \\/| (  )  |\n",
      "| (____  | | /   |\n",
      "(_____ \\ | (/ /) |\n",
      "      ) )|   / | |\n",
      "/\\____) )|  (__) |\n",
      "\\______/ (_______)\n",
      "                  \n",
      "\n",
      "Bot: Возраст Илона Маска - 50 лет.\n",
      "User: \n"
     ]
    }
   ],
   "source": [
    "chat_history = []\n",
    "while True:\n",
    "    user_input = input(\"Вы: \")\n",
    "    print(f\"Пользователь: {user_input}\")\n",
    "    if user_input == \"\":\n",
    "        break\n",
    "    result = agent_executor.invoke(\n",
    "        {\n",
    "            \"chat_history\": chat_history,\n",
    "            \"input\": user_input,\n",
    "        }\n",
    "    )\n",
    "    chat_history.append(HumanMessage(content=user_input))\n",
    "    chat_history.append(AIMessage(content=result[\"output\"]))\n",
    "    print(f\"Агент: {result['output']}\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
